import QtQuick 2.0
import Qt3D 1.0
import Qt3D.Shapes 1.0
import "js/BlockInfo.js" as BI

CubeEx{
    id: _root
    scale: 1//0.95
    property color color: "#dd0000"
    property real angle: 0
    property real angleRad: angle * Math.PI / 180
    property variant origin: Qt.vector3d(0, 0, 0)
    property variant axis: Qt.vector3d(0, 0, 0)
    property int textureMode: 0     //0:pastel 1:normal 2:curse

    effect: Effect {
        id: _effect
        color: _root.color
        material: Material{
//            ambientColor: Qt.rgba(1, 1, 1, 1)
//            diffuseColor: Qt.rgba(0, 0, 0, 1)
            specularColor: Qt.rgba(1, 1, 1, 1)
        }
    }
    transform: [
        Rotation3D {
            id: _rotate
            angle: _root.angle
            axis: _root.axis
            origin: _root.origin
        }
        //キューブの９０ターン用
        ,Translation3D{id: _t1}
        ,Rotation3DforBlock {id:_a1},Rotation3DforBlock {id:_a2},Rotation3DforBlock {id:_a3},Rotation3DforBlock {id:_a4}
        ,Rotation3DforBlock {id:_a5},Rotation3DforBlock {id:_a6},Rotation3DforBlock {id:_a7},Rotation3DforBlock {id:_a8}
        ,Rotation3DforBlock {id:_a9},Rotation3DforBlock {id:_a10},Rotation3DforBlock {id:_a11},Rotation3DforBlock {id:_a12}
    ]

    Behavior on x{
        NumberAnimation{ id: _animX; duration: 200  }
    }
    Behavior on y{
        NumberAnimation{ id: _animY; duration: 200  }
    }
    Behavior on z{
        NumberAnimation{ id: _animZ; duration: 200  }
    }
    Behavior on angle{
        NumberAnimation{ id: _animAngle; duration: 200  }
    }

    property bool running: runningRotetaLock | runningRotate | _animX.running | _animY.running | _animZ.running | _animAngle.running
    property bool runningRotetaLock: false
    property bool runningRotate: _a1.running | _a2.running | _a3.running | _a4.running | _a5.running | _a6.running | _a7.running | _a8.running | _a9.running | _a10.running | _a11.running | _a12.running
    onRunningRotateChanged: {
        if(runningRotate === false){
            var now_angle = [0, 0, 0];
            var rotate_count = [0, 0, 0];
            var axis = [Qt.vector3d(1, 0, 0), Qt.vector3d(0, 1, 0), Qt.vector3d(0, 0, 1)]
            var i = 0;
            var j = 0;
            var k = 0;
            var c = 0;
            var iscut = false;
            //アニメーションを停止
            c = 0;
            for(i=2; i<_root.transform.length; i++){
                _root.transform[i].enabled = false;     //これしないとangle変化のアニメが始まってループする
                if(_root.transform[i].angle !== 0){
                    c += 1;
                }
            }
            if(c >= 10){
                var position = Qt.vector3d(0, 0, 0);
                var relative = Qt.vector3d(0, 0, 0);
                var dir = Qt.vector3d(0, 0, 0);   //今の向き
                //今の位置
                position = realPos();
                //今の向き
                dir = realDirection();
                //相対位置
                relative.x = position.x - _root.x;
                relative.y = position.y - _root.y;
                relative.z = position.z - _root.z;

                var tmp_pos = realPos();    //デバッグ用
                var tmp_dir = realDirection();   //元の向き

                //詰める
                packTransform(relative);
                //平行移動
                adjustTransform(relative, dir);

                //error list
                //位置の違い
                position = realPos();
                if(tmp_pos.x !== position.x || tmp_pos.y !== position.y || tmp_pos.z !== position.z){
                    console.debug("ERR:" + _root.color + "-----");
                    relative.x = (tmp_pos.x - _root.x);
                    relative.y = (tmp_pos.y - _root.y);
                    relative.z = (tmp_pos.z - _root.z);
                    console.debug(" " + _root.x + ", " + _root.y + ", " + _root.z
                                  + " / " + tmp_pos.x + ", " + tmp_pos.y + ", " + tmp_pos.z
                                  + " -> " + position.x + ", " + position.y + ", " + position.z
                                  + " => " + relative.x + ", " + relative.y + ", " + relative.z
                                  );
                    console.debug(" " + _root.transform[1].translate.x + ", " + _root.transform[1].translate.y + ", " + _root.transform[1].translate.z);
                    for(i=2; i<_root.transform.length; i++){
                        console.debug(" " + _root.transform[i].angle
                                      + " / " + _root.transform[i].axis.x + ", " + _root.transform[i].axis.y + ", " + _root.transform[i].axis.z
                                      + " / " + _root.transform[i].origin.x + ", " + _root.transform[i].origin.y + ", " + _root.transform[i].origin.z
                                      + " / " + _root.transform[i].isSpin);
                    }
                }
                //向き違い
                dir = realDirection();
                if(dir !== tmp_dir){
                    console.debug("ERR:" + _root.color + "======");
                    console.debug(" " + tmp_dir + " -> " + dir);
                }
            }

            //ロック解除
            runningRotetaLock = false;
        }
    }

    //クリア
    function clearTransform(){
        _root.transform[1].translate = Qt.vector3d(0, 0, 0);
        for(var i=2; i<_root.transform.length; i++){
            _root.transform[i].angle = 0;
        }
    }
    //詰めて回転を自転にする
    function packTransform(relative){
        var dir = -1;
        var i=0;
        var len=0;

        //向きを調べる
        dir = realDirection();

        //該当のIDのデータを探す
        len = Math.round(BI.MAP_ADJ_ROTATE.length/9);
        for(i=0; i<len; i++){
            if(dir === BI.MAP_ADJ_ROTATE[i*9]){
                break;
            }
        }
        //回転情報をセット
        _root.transform[2].angle = BI.MAP_ADJ_ROTATE[i*9+1];
        _root.transform[2].axis.x = BI.MAP_ADJ_ROTATE[i*9+2];
        _root.transform[2].axis.y = BI.MAP_ADJ_ROTATE[i*9+3];
        _root.transform[2].axis.z = BI.MAP_ADJ_ROTATE[i*9+4];
        _root.transform[2].origin.x = relative.x;
        _root.transform[2].origin.y = relative.y;
        _root.transform[2].origin.z = relative.z;
        _root.transform[2].isSpin = true;
        _root.transform[3].angle = BI.MAP_ADJ_ROTATE[i*9+5];
        _root.transform[3].axis.x = BI.MAP_ADJ_ROTATE[i*9+6];
        _root.transform[3].axis.y = BI.MAP_ADJ_ROTATE[i*9+7];
        _root.transform[3].axis.z = BI.MAP_ADJ_ROTATE[i*9+8];
        _root.transform[3].origin.x = relative.x;
        _root.transform[3].origin.y = relative.y;
        _root.transform[3].origin.z = relative.z;
        _root.transform[3].isSpin = true;
        //のこりをクリア
        for(i=4; i<_root.transform.length; i++){
            _root.transform[i].angle = 0;
        }
    }
    //位置の調節
    function adjustTransform(relative, dir){
        //平行移動
        _root.transform[1].translate.x = relative.x;
        _root.transform[1].translate.y = relative.y;
        _root.transform[1].translate.z = relative.z;
    }

    //回転させる
    function rotateBlock(isPlus, axis, origin){
        var angle = 0;
        var now_angle = 0;
        var i=0;

        if(running){
        }else{
            //ロック
            runningRotetaLock = true;
            //向き確定
            if(isPlus){
                angle = 90;
            }else{
                angle = -90;
            }
            //追加
            for(i=2; i<_root.transform.length; i++){
                _root.transform[i].enabled = true;  //なかったとこにする時falseにするので
                if(_root.transform[i].angle === 0){
                    _root.transform[i].angle = angle;
                    _root.transform[i].axis = axis;
                    _root.transform[i].origin = origin;
                    _root.transform[i].isSpin = false;
                    break;
                }
            }
        }
    }
    //X軸で90度回転
    function rotateX(isPlus){
        rotateBlock(isPlus, Qt.vector3d(1, 0, 0), Qt.vector3d(-_root.x, -_root.y, -_root.z));
    }
    //Y軸で90度回転
    function rotateY(isPlus){
        rotateBlock(isPlus, Qt.vector3d(0, 1, 0), Qt.vector3d(-_root.x, -_root.y, -_root.z));
    }
    //Z軸で90度回転
    function rotateZ(isPlus){
        rotateBlock(isPlus, Qt.vector3d(0, 0, 1), Qt.vector3d(-_root.x, -_root.y, -_root.z));
    }

    //実際の位置を計算
    function realPos(){
        return calcPosition(_root.x, _root.y, _root.z, true, false);
    }
    function calcPosition(x, y, z, isround, isCalcSpin){
        var pos = Qt.vector3d(0, 0, 0);
        var dx = 0;
        var dy = 0;
        var dz = 0;
        var rad = 0;

        //平行移動分
        if(isCalcSpin){
            //自転計算時は平行移動なし
        }else{
            x += _root.transform[1].translate.x;
            y += _root.transform[1].translate.y;
            z += _root.transform[1].translate.z;
        }

        //回転分
        for(var i=2; i<_root.transform.length; i++){
            rad = _root.transform[i].angle * Math.PI / 180;
            if(rad === 0){
                break;
            }else if(_root.transform[i].isSpin === true && isCalcSpin === false){
                //自転は計算しない
                dx = x;
                dy = y;
                dz = z;
            }else if(_root.transform[i].axis.x === 1){
                dx = x;
                dy = y * Math.cos(rad) - z * Math.sin(rad);
                dz = y * Math.sin(rad) + z * Math.cos(rad);
            }else if(_root.transform[i].axis.y === 1){
                dx = z * Math.sin(rad) + x * Math.cos(rad);
                dy = y;
                dz = z * Math.cos(rad) - x * Math.sin(rad);
            }else if(_root.transform[i].axis.z === 1){
                dx = x * Math.cos(rad) - y * Math.sin(rad);
                dy = x * Math.sin(rad) + y * Math.cos(rad);
                dz = z;
            }
            if(isround){
                x = Math.round(dx);
                y = Math.round(dy);
                z = Math.round(dz);
            }else{
                x = dx;
                y = dy;
                z = dz;
            }
        }
        pos.x = x;
        pos.y = y;
        pos.z = z;
        return pos;
    }

    //0, 0.5, -0.5に四捨五入する
    function roundHalf(data){
        var ret = Qt.vector3d(0, 0, 0);
        if(data.x > 0.25){
            ret.x = 0.5;
        }else if(data.x < -0.25){
            ret.x = -0.5;
        }else{
            ret.x = 0;
        }
        if(data.y > 0.25){
            ret.y = 0.5;
        }else if(data.y < -0.25){
            ret.y = -0.5;
        }else{
            ret.y = 0;
        }
        if(data.z > 0.25){
            ret.z = 0.5;
        }else if(data.z < -0.25){
            ret.z = -0.5;
        }else{
            ret.z = 0;
        }
        return ret;
    }

    //向きを計算する
    function realDirection(){
        var top = Qt.vector3d(0, 0, 0);
        var bottom = Qt.vector3d(0, 0, 0);
        var north = Qt.vector3d(0, 0, 0);
        var south = Qt.vector3d(0, 0, 0);

        //今の位置
        top = calcPosition(topPos.x, topPos.y, topPos.z, false, true);
        bottom = calcPosition(bottomPos.x, bottomPos.y, bottomPos.z, false, true);
        north = calcPosition(northPos.x, northPos.y, northPos.z, false, true);
        south = calcPosition(southPos.x, southPos.y, southPos.z, false, true);
//        console.debug("POS1:"
//                      + " / " + top.x + ", " + top.y + ", " + top.z
//                      + " / " + bottom.x + ", " + bottom.y + ", " + bottom.z
//                      + " / " + north.x + ", " + north.y + ", " + north.z
//                      + " / " + south.x + ", " + south.y + ", " + south.z)
        top = roundHalf(top);
        bottom = roundHalf(bottom);
        north = roundHalf(north);
        south = roundHalf(south);
//        console.debug("POS2:"
//                      + " / " + top.x + ", " + top.y + ", " + top.z
//                      + " / " + bottom.x + ", " + bottom.y + ", " + bottom.z
//                      + " / " + north.x + ", " + north.y + ", " + north.z
//                      + " / " + south.x + ", " + south.y + ", " + south.z)

        return calcDir(top, bottom, north, south);
    }

    //向きの算出
    function calcDir(topPosition, bottomPosition, northPosition, southPosition){
        var tb = Qt.vector3d(0, 0, 0);
        var ns = Qt.vector3d(0, 0, 0);
        var ret = -1;

        tb.x = checkCmd(topPosition.x - bottomPosition.x);
        tb.y = checkCmd(topPosition.y - bottomPosition.y);
        tb.z = checkCmd(topPosition.z - bottomPosition.z);
        ns.x = checkCmd(northPosition.x - southPosition.x);
        ns.y = checkCmd(northPosition.y - southPosition.y);
        ns.z = checkCmd(northPosition.z - southPosition.z);

        var size = 7;
        var len = Math.floor(BI.MAP_CHK_ROTATE.length/size);
        for(var i=0; i<len; i++){
            if((tb.x === BI.MAP_CHK_ROTATE[i*size + 1])
                    && (tb.y === BI.MAP_CHK_ROTATE[i*size + 2])
                    && (tb.z === BI.MAP_CHK_ROTATE[i*size + 3])
                    && (ns.x === BI.MAP_CHK_ROTATE[i*size + 4])
                    && (ns.y === BI.MAP_CHK_ROTATE[i*size + 5])
                    && (ns.z === BI.MAP_CHK_ROTATE[i*size + 6])
                    ){
                ret = BI.MAP_CHK_ROTATE[i*size + 0];
                break;
            }
        }
//        console.debug("CALC:" + _root.color + ":" + ret + ":" + tb.x + ", " + tb.y + ", " + tb.z
//                      + " / " + ns.x + ", " + ns.y + ", " + ns.z);
        return ret;
    }
    function checkCmd(value){
        var ret = 0;
        if(value < 0){
            ret = -1;
        }else if(value > 0){
            ret = 1;
        }else{
            ret = 0;
        }
        return ret;
    }

    StateGroup{
        states:[
            State{
                name: "normal"
                when: textureMode == 1
                PropertyChanges {
                    target: _root
                    texturePath: "Normal"
                }
            },
            State{
                name: "curse"
                when: textureMode == 2
                PropertyChanges {
                    target: _root
                    texturePath: "Curse"
                }
            }
        ]
    }
}
